#include "amethyst_interface.h"
#include "crc16.h"



int ReadSPIMessage(void *buff,int msglength);
int WriteSPIMessage(void *buff,int msglength);
void gpio_write_to_spi(int on);
static uint16 g_PMIFcommandSequenceNumber=0;

//PMIFMsgLengthT  AmethifSendMessage(uint8 *buf, PMIFMsgLengthT length);


int AmethifCheckCrc(  uint8* pMsg)
{
  PMIFMsgHeaderT *pHeader;
  PMIFMsgFooterT *pRecievedFooter, computedFooter;
  int footerIndex;
  int startData4CRCIndex;
  int length4CRC;
  int rc=FALSE;
   pHeader =  (PMIFMsgHeaderT*)pMsg;
  printf("%s len(%d) type(%d) seq(%d)\n\r",__func__,pHeader->msgLength & 0xff,pHeader->msgType & 0xff,pHeader->commandSequenceNumber & 0xffff); 
  footerIndex = pHeader->msgLength-sizeof(computedFooter)+sizeof(pHeader->msgLength);
  startData4CRCIndex = sizeof(pHeader->msgLength);
  length4CRC= pHeader->msgLength-sizeof(computedFooter );
  //Get out if length is illegal
  if ( length4CRC > MAX_PAIF_MESSAGE_SIZE-sizeof(computedFooter ))
	  return rc;

  //Compute the crc form the message arrived
  pRecievedFooter =(PMIFMsgFooterT*) &pMsg[footerIndex ];
  computedFooter.crc = crc16_ccitt(&pMsg[startData4CRCIndex],length4CRC );
  //Compare the comuted and the messasge CRCs
  rc = pRecievedFooter->crc == computedFooter.crc;
  return rc;
}

PMIFMsgLengthT  AmethifSendMessage(uint8 *buf, PMIFMsgLengthT length)//message length 
{

    PMIFMsgFooterT footer;
    PMIFMsgLengthT msgLength;
    PMIFMsgHeaderT* pHeader = (PMIFMsgHeaderT*) buf;
    PMIFMsgFooterT *pFooter;
    uint16 crcLength;
    uint16 crcStartIdx ;
    // length of message for crc = datalength - length field - size of crc.
    // start of message for crc is after the length field of the header
    crcStartIdx= sizeof(pHeader->msgLength);
    crcLength=length-crcStartIdx-sizeof(footer);
    // a) Update the length field , message counter & message time
    pHeader->msgLength = crcLength+sizeof(footer);
    pHeader->commandSequenceNumber=g_PMIFcommandSequenceNumber++;  //use the request counter
    // b) Compute CRC and update the crc field in the message header.
    footer.crc =( uint16) crc16_ccitt(&buf[crcStartIdx], (uint16) crcLength);
    // c) Copy the crc to the message. The crc is added after the message.
    msgLength = length-sizeof(footer);//+  crcStartIdx;
    pFooter= (PMIFMsgFooterT*) &buf[msgLength];
    *pFooter = footer;
//    int tst;
//    tst = AmethifCheckCrc(  buf )  ;//test crc
    return length;
 
}

int m_debug_slice=0;

int GetCameraSlice(unsigned char *buffer,int offset, int length);


void AmethifHandleRequestImageSliceMsg(uint8* pMsg, PMIFMsgLengthT* msgLength)        
{	
  //biuild ansImageSlice
    uint8 b;
    int i;
    PMIFRequestImageSliceMsgT* pImsg = (PMIFRequestImageSliceMsgT*)pMsg;
    PMIFAnsImageSliceMsgT* pOmsg = (PMIFAnsImageSliceMsgT*)pMsg;
    PMIFRequestImageSliceMsgT inMsg;
    memcpy(&inMsg , pImsg, sizeof(inMsg));
    pOmsg->header.msgType=PMIFAnsImageSliceMsgType;
 
   pOmsg->fileType = inMsg.fileType ;
   pOmsg->cropType = inMsg.cropType;
   pOmsg->frameSize=4;
   pOmsg->padding=0;
   pOmsg->eventNumber = inMsg.eventNumber;
   pOmsg->imageFileNumber = inMsg.imageFileNumber;  
   pOmsg->sliceNumber = inMsg.sliceNumber;
   pOmsg->totalslicesInFile=16;
   b = (pOmsg->sliceNumber << 4);
   if(m_debug_slice==0)
	   GetCameraSlice(pOmsg->payload,pOmsg->sliceNumber*MAX_PAYLOAD_BYTES_LENGTH,MAX_PAYLOAD_BYTES_LENGTH);
   if(m_debug_slice)
   for(i=0;i< MAX_PAYLOAD_BYTES_LENGTH; i++)
   {
      pOmsg->payload[i]= b + i;
   }
   *msgLength = sizeof( *pOmsg);
   PRINTF("AmethifHandleRequestImageSliceMsgp Omsg->sliceNumber=%d RxSeq %d TxSeq %d\n",
          pOmsg->sliceNumber,
          inMsg.header.commandSequenceNumber,
          pOmsg->header.commandSequenceNumber); 
 
}



PMIFMsgLengthT  AmethifHandleMessage( uint8* pMsg)
{
  
  
  
  PMIFMsgHeaderT *pHeader;
  PMIFMsgLengthT outlen=0;
  int crcOk;
  pHeader = (PMIFMsgHeaderT*)pMsg;
  PMIFMsgLengthT msgLength=pHeader->msgLength;
  crcOk = AmethifCheckCrc(pMsg );
  if(crcOk == FALSE )
  {
     // AmethifBuildPMIFNackMsg( pMsg,&msgLength);
    PRINTF("crc failed\n");
    return outlen;
  }
  else
  { 
   switch ( pHeader->msgType)
    {
      
      case   PMIFRequestStatusMsgType:             // Request a status report (includes hunting alerts)
         break;
      case  PMIFRequestSetParameterMsgType:       // Set parameters for the WEM operation
         break;
      case  PMIFRequestGetParameterMsgType:       // Get the value currently set to a parameter
         break;
      case  PMIFRequestHuntingModeMsgType:        // Request the Amethyst to start/stop hunting for movement using the current parameters
        break;
      case  PMIFRequestImageCaptureMsgType:        // Request the Amethyst to take a snapshot at requested time of day or a series of times using the current parameters
        break;
      case  PMIFRequestEventInfoMsgType:           // Request information about a specific event
        break;
      case  PMIFRequestFileInfoMsgType:            // Request information about a specific image file in a specific resolution type and crop
        break;
      case  PMIFRequestImageSliceMsgType:          // Request a specific slice from a specific image file
        AmethifHandleRequestImageSliceMsg(   pMsg,  &msgLength); 
        break;
      case  PMIFRequestClearBufferMsgType:         // Clear image file buffer
        break;
      case PMIFRequestShutDownMsgType:            // Request Shutdown 
        break;
      //   AMETHYST to PEARL
      case   PMIFAckMsgType:                   // Acknowledge reception of the message
           PRINTF("Got ACK\n");
        break;
      case   PMIFNAckMsgType:                   // Reason for not receiving the message 
          PRINTF("Got NACK\n");
        break;
      case   PMIFAnsStatusMsgType:      // Report status
        break;
      case   PMIFAnsEventInfoMsgType:         // Description of a specific event.
        break;
      case   PMIFAnsFileInfoMsgType:           // Description of a specific file in a specific event
        break;
      case   PMIFAnsImageSliceMsgType:         // Deliver a slice of an image file
    //    AmethifHandleAnsImageSliceMsg (   pMsg,  &msgLength); 
 
        break;
      case   PMIFAnsParameterMsgType:          // Report current value of a parameter
        break;//
      default:
        break;           
    } //switch

  }
  if(msgLength>0)
	  outlen = AmethifSendMessage((uint8*) pMsg, msgLength);//data length without footer
  return outlen;
}

static int m_finish=0;

void AmethPearlTask(void *pvParameters){
	int ret=0;
	uint8 CurrentMessage[PEARL_INPUT_BUFFER_SIZE];
	PMIFMsgLengthT outlen;
	int i;
	/* Current message size */
	//uint16 CurrentMessageSize = 0;	
	while(!m_finish){
		ret = ReadSPIMessage(CurrentMessage,PEARL_INPUT_BUFFER_SIZE);
		if(ret == PEARL_INPUT_BUFFER_SIZE){
			outlen = PEARL_INPUT_BUFFER_SIZE-10;
			if(CurrentMessage[8] == 0xd7 && CurrentMessage[9]==0){
#if 1
				outlen = AmethifHandleMessage(&CurrentMessage[10]);
				if(outlen <=0){
					continue;
				}
#endif				
			}
			else{
#if 0				
				int ii;
				int testc=0;
				//printf("wrong data (%d)[",i);
				for(ii=0;ii<PEARL_INPUT_BUFFER_SIZE;ii++){
					if(CurrentMessage[ii] )
						testc++;
					//printf("%x,",CurrentMessage[ii] & 0xff);
				}
				//printf("]\n\r");
				if(testc)
#endif					
				continue;				
			}
			ret = WriteSPIMessage(&CurrentMessage[10],outlen);
			printf("send %d \n\r",ret);
		}
		else{
			//	gpio_write_to_spi(0);
			//	OS_MSleep(100);
			//	gpio_write_to_spi(1);
				printf("spi read time out \n\r");
				
			}
	}
	
}


int Amethyst_Test_Init(int debug){
	m_finish =0;
	g_PMIFcommandSequenceNumber=0;
	m_debug_slice = debug;
}

int Amethyst_Test_Term(void){
	m_finish = 1;
}


